package edu.cth.stud.accelerateit.view.android;

import java.beans.PropertyChangeEvent;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputFilter;
import android.text.InputType;
import android.text.TextWatcher;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import edu.cth.stud.accelerateit.R;
import edu.cth.stud.accelerateit.core.Word;
import edu.cth.stud.accelerateit.view.GUIController;

public class FindAWordActivity extends Activity implements IAndroidGUIComponent {

	private Button goBackButton;
	private Button searchButton;
	private EditText lettersInput;
	private EditText[] squares = new EditText[5];
	private TextView resultsText;
	private TextView gameboardText;
	private TextView yourLettersText;
	
	private InputFilter[] squaresInputFilters = new InputFilter[2];
	private InputFilter[] lettersInputFilters = new InputFilter[2];
	private TextWatcher textWatcher;
	
	private static final String PREFS_NAME = "WordFinderSettings";
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// creating the input filter in a separate method, for code structure:
		createInputFilters();

		// create the text change listener in a separate method, for code
		// structure:
		createTextWatcher();

		// link content, for code structure:
		linkContent();

		// Load settings:
		loadSettings();
		
		// Register this activity/view with the GUIController:
		GUIController.getInstance().registerListener(this);
	}

	private void loadSettings() {
		SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
		int textColor = settings.getInt("textColor", Color.WHITE);
		int backgroundColor = settings.getInt("backgroundColor", Color.BLACK);
		this.findViewById(R.id.fawScreen).setBackgroundColor(backgroundColor);
		resultsText.setTextColor(textColor);
		gameboardText.setTextColor(textColor);
		yourLettersText.setTextColor(textColor);
	}

	private void createTextWatcher() {
		// TODO: find the requirement that says the search button may only be
		// enabled when information has been entered and copy its ID here.
		textWatcher = new TextWatcher() {

			@Override
			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
				// Not needed as of now.
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				// Not needed as of now.
			}

			@Override
			public void afterTextChanged(Editable s) {
				if (s.length() == 0) {
					searchButton.setEnabled(false);
				} else {
					searchButton.setEnabled(true);
				}
			}
		};
	}

	private void createInputFilters() {
		// This method is separate for code structure.

		// First, we create the letters-only filter:
		InputFilter letterFilter = new InputFilter() {
			public CharSequence filter(CharSequence source, int start, int end,
					android.text.Spanned dest, int dstart, int dend) {
				for (int i = start; i < end; i++) {
					if (!Character.isLetter(source.charAt(i))) {
						return "";
					}
				}
				return null;
			}
		};

		// Then, we create two length filters:
		InputFilter oneCharFilter = new InputFilter.LengthFilter(1);
		InputFilter eightCharFilter = new InputFilter.LengthFilter(8);

		// The "squares" should allow only 1 char:
		squaresInputFilters[0] = letterFilter;
		squaresInputFilters[1] = oneCharFilter;

		// The letters input box should allow a maximum of 8 chars:
		lettersInputFilters[0] = letterFilter;
		lettersInputFilters[1] = eightCharFilter;
	}

	private void linkContent() {
		// set the content view to faw_view.xml:
		setContentView(R.layout.faw_view);

		// Connect buttons:
		goBackButton = (Button) this.findViewById(R.id.goBackButton);
		searchButton = (Button) this.findViewById(R.id.searchButton);
		
		// Connect text squares:
		squares[0] = (EditText) this.findViewById(R.id.square1);
		squares[1] = (EditText) this.findViewById(R.id.square2);
		squares[2] = (EditText) this.findViewById(R.id.square3);
		squares[3] = (EditText) this.findViewById(R.id.square4);
		squares[4] = (EditText) this.findViewById(R.id.square5);
		lettersInput = (EditText) this.findViewById(R.id.lettersInput);

		resultsText = (TextView) this.findViewById(R.id.resultsView);
		yourLettersText = (TextView) this.findViewById(R.id.fawYourLettersText);
		gameboardText = (TextView) this.findViewById(R.id.fawFillInText);
		
		
		// Make the resultsText scrollable:
		resultsText.setMovementMethod(new ScrollingMovementMethod());
		
		// Setting up the keyboard input filters and types:
		for (int i = 0; i < 5; i++) {
			squares[i].setFilters(squaresInputFilters);
			squares[i].setInputType(InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
		}
		lettersInput.setInputType(InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
		lettersInput.setFilters(lettersInputFilters);

		// Add the text change listener to the lettersInput:
		lettersInput.addTextChangedListener(textWatcher);
		// On a related note, make sure the searchButton is disabled when we
		// start the application:
		searchButton.setEnabled(false);

		this.goBackButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				goBack();
			}
		});

		this.searchButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				search();
			}
		});
	}

	private void goBack() {
		// Required to keep down the activity count:
		finish();
		GUIController.getInstance().unregisterListener(this);

		Intent showMainMenu = new Intent(this.getApplicationContext(),
				WordFinderActivity.class);
		startActivity(showMainMenu);
	}

	/**
	 * This method is entered when the device's user hits the "back" button.
	 * TODO: if the back button is pressed in any non-main-menu screen, the
	 * application is to behave in a certain way. Find the requirement ID for
	 * this and enter it here in this comment field.
	 */
	@Override
	public void onBackPressed() {
		goBack();
	}

	private void search() {
		String gameBoard = "";
		String temp = "";

		for (int i = 0; i < 5; i++) {
			temp = squares[i].getText().toString();

			if (temp.equals("")) {
				// Make sure temp is represented by a "_" representing an empty
				// square.
				temp = "_";
			} else {
				temp = temp.toLowerCase();
			}
			gameBoard = gameBoard + temp;
		}

		// Retrieve the user's entry into lettersInput:
		String availableLetters = lettersInput.getText().toString()
				.toLowerCase().trim();

		Log.d("WordFinder", "Performing a search for: " + gameBoard + ", "
				+ availableLetters);
		GUIController.getInstance().enterDictionarySearch(availableLetters,
				gameBoard);
	}

	@Override
	public void propertyChange(PropertyChangeEvent event) {
		// If the event was a shutdown command:
		if (event.getPropertyName().equals("Shutdown")) {
			GUIController.getInstance().unregisterListener(this);
			finish();
		}
		// If the event was a word list returned from a search:
		else if (event.getPropertyName().equals("WordList")) {
			Word[] results = (Word[]) event.getNewValue();
			// First, we find how many results were found:
			int resultsAmount = results.length;
			// Start building the string that goes in resultsText:
			String resultsString = "";
			if (resultsAmount == 0) {
				resultsString = "Sorry, no results were found";
			} else {
				resultsString = resultsAmount + " results were found\nBest results:";
				// Add the results.
				for (int i = 0; i < results.length; i++) {
					try {
						resultsString += "\n" + results[i].toString();
					} catch (ArrayIndexOutOfBoundsException e) {
						// Just in case.
						break;
					}
				}
			}
			
			// Finally, set the TextView:
			resultsText.setText(resultsString);
		}
	}
}
